/**
 *
 */
package com.cmcc.awareness;

import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * @Date 2018年4月11日 上午11:27:03
 * @author Amish
 *
 */
public class HttpProtoRuleField {
	private static Logger logger = LogManager.getLogger(HttpProtoRuleField.class);
	/**
	 * eg：
	 * Uri=appid=com.qiyi
	 */
	private String field;
	private String ruleStr;//初始规则库中配置的字符串
	private String ruleStrRegex;
	
	//用于支持Data字段
	private int data_start;
	private int data_end;
	
	public boolean distinguish(org.apache.http.HttpRequest httpRequest){
		
		if(field.equals("Uri")){
			boolean isMatch = Pattern.compile(ruleStrRegex).matcher(httpRequest.getRequestLine().getUri()).matches();
//			if(isMatch){
//				logger.info("HttpProtoRuleField match : "+field+"="+ruleStr+" ruleRegex: <"+ruleStrRegex+" >");
//			}
			return isMatch;
		}else if(!field.equals("Data")){
			Header header = httpRequest.getFirstHeader(field);
			if(header != null){
				boolean isMatch = Pattern.compile(ruleStrRegex).matcher(header.toString()).matches();
				
//				if(isMatch){
//					logger.info("HttpProtoRuleField match : "+field+"="+ruleStr+" ruleRegex: <"+ruleStrRegex+" >");
//				}
				
				return isMatch;
			}
			return false;
		}else{
			//TODO
			return false;
		}
	}
	
	/**
	 * TOFIX 此处暂时默认Tls_server 和 id-at-commonName只会同时存在一个字段
	 * @param https_Tls_server
	 * @param https_id_at_commonName
	 * @return
	 */
	public boolean distinguish(String https_Tls_server , String https_id_at_commonName){
		
		if(!field.equals("Tls_server") && !field.equals("id-at-commonName")){
		    return false;	
		}
		
		if(https_Tls_server != null || !"".equals(https_Tls_server)){
			boolean isMatch = Pattern.compile(ruleStrRegex).matcher(https_Tls_server).matches();
			return isMatch;
		}
		
		if(https_id_at_commonName !=null || !"".equals(https_id_at_commonName)){
			boolean isMatch = Pattern.compile(ruleStrRegex).matcher(https_Tls_server).matches();
			return isMatch;
		}
		
		return false;
		
	}
	
	
	/**
	 * (1)Data的规则解析
	 * (2)Request标准字段的规则解析
	 */
	private void dealRuleStr(){
		if(!field.equals("Data")){
			 encodeRegex(ruleStr);
		}else{
			int rightBracket = ruleStr.indexOf("]");
			String ruleStr_part2 = ruleStr.substring(rightBracket+1);
			int shortLine = ruleStr.indexOf("-");
			if(shortLine != -1){//[a-b]
				data_start = Integer.valueOf(ruleStr.substring(1, shortLine));
				data_end = Integer.valueOf(ruleStr.substring(shortLine+1, rightBracket));
			}else{//[$n]
				data_start = Integer.valueOf(ruleStr.substring(ruleStr.indexOf("$")+1, rightBracket));
				data_end = Integer.MAX_VALUE;
			}
			encodeRegex(ruleStr_part2);
		}
	}
	/**
	 * 原规则字符串解释：规则库元字符，* ^ $ [ ] -
	 * (1)%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE:直接当字符串处理
	 * (2)* 表示任意个(>=0)ASCII字符
	 * (3)^ 表示匹配源串的开头
	 * (4)$ 表示匹配源串的结尾
	 * 
	 * 生成Regex逻辑：
	 * (1)TOFIX 对于Ox开头的规则配置，目前考虑直接去掉Ox然后后面当字符串
	 * (2)检查原规则字符串是否有.,如果有用\\.来替换
	 * (3)检查原规则字符串是否有*,如果有，用.*替换
	 * (4)检查原规则字符串中是否有^或$,如果都没有,在原规则字符串  前后  加上.*,实现任意位置匹配该字符串
	 * (5)检查原规则字符串中是否有^或$,如果只有^,在原规则字符串  后  加上.*。如果只有$,在原规则字符串  前  加上.*。
	 */
	private void encodeRegex(String ruleStr){
		ruleStrRegex = ruleStr.replaceAll("0x", "");
		ruleStrRegex = ruleStrRegex.replaceAll("\\.", "\\\\.");
		ruleStrRegex = ruleStrRegex.replaceAll("\\*", ".*");
		boolean startWithCaret =  ruleStrRegex.startsWith("^");
		boolean endWithDollar = ruleStrRegex.endsWith("$");
		if(!startWithCaret && !endWithDollar){
			ruleStrRegex = ".*"+ruleStrRegex+".*";
		}else if(startWithCaret && !endWithDollar){
			ruleStrRegex = ruleStrRegex+".*";
		}else if(!startWithCaret && endWithDollar){
			ruleStrRegex = ".*"+ruleStrRegex;
		}
	}
	
	

	public String getField() {
		return field;
	}

	public void setField(String field) {
		this.field = field;
	}

	public String getRuleStr() {
		return ruleStr;
	}

	public void setRuleStr(String ruleStr) {
		this.ruleStr = ruleStr;
		this.dealRuleStr();//处理规则字符串，并编码生成Regex
	}

	public String getRuleStrRegex() {
		return ruleStrRegex;
	}
	
	public int getData_start() {
		return data_start;
	}

	public int getData_end() {
		return data_end;
	}

	/**
	 * only for test
	 * @param args
	 */
	public static void main(String args[]){
		HttpProtoRuleField hprf = new HttpProtoRuleField();	
		
		hprf.setField("Host");
		hprf.setRuleStr("0x1234567890abcdefm/");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Host");
		hprf.setRuleStr(".alicdn.com/");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Host");
		hprf.setRuleStr(".ali.*cdn.com/");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Host");
		hprf.setRuleStr("^.alicdn.com/");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Host");
		hprf.setRuleStr(".alicdn.com/$");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Data");
		hprf.setRuleStr("[$10]0x1234abcd");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getData_start());
		System.out.println(hprf.getData_end());
		System.out.println(hprf.getRuleStrRegex());
		
		hprf.setField("Data");
		hprf.setRuleStr("[123-321]0x1234abcd");
		System.out.println(hprf.getRuleStr());
		System.out.println(hprf.getData_start());
		System.out.println(hprf.getData_end());
		System.out.println(hprf.getRuleStrRegex());
	}

}
